package com.bfl.sa.common.mybatis.type;

import org.apache.commons.codec.binary.Hex;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.mybatis.spring.MyBatisSystemException;

import java.io.*;
import java.sql.*;

public class ObjectSerializeUserType extends BaseTypeHandler {

    private Object deserializeObject(String hexStr) {
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(new ByteArrayInputStream(Hex.decodeHex(hexStr.toCharArray())));
            return ois.readObject();
        } catch (Exception e) {
            throw new MyBatisSystemException(e);
        } finally {
            try {
                if (ois != null) {
                    ois.close();
                }
            } catch (IOException ignored) { }
        }
    }

    /**
     * 本方法将在数据保存时被调用
     * 我们可以通过PreparedStateme将自定义数据写入到对应的数据库表字段
     */
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Object o, JdbcType jdbcType) throws SQLException {
        ObjectOutputStream oos = null;
        if (o == null) {
            ps.setNull(i, Types.VARCHAR);
        } else {
            try {
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                oos = new ObjectOutputStream(bos);
                oos.writeObject(o);
                oos.close();

                byte[] objectBytes = bos.toByteArray();
                String hexStr = Hex.encodeHexString(objectBytes);

                ps.setString(i, hexStr);
            } catch (Exception e) {
                throw new MyBatisSystemException(e);
            } finally {
                try {
                    if (oos != null) {
                        oos.close();
                    }
                } catch (IOException ignored) { }
            }
        }
    }

    @Override
    public Object getNullableResult(ResultSet rs, String s) throws SQLException {
        return deserializeObject(rs.getString(s));
    }

    @Override
    public Object getNullableResult(ResultSet rs, int i) throws SQLException {
        return deserializeObject(rs.getString(i));
    }

    @Override
    public Object getNullableResult(CallableStatement cs, int i) throws SQLException {
        return deserializeObject(cs.getString(i));
    }

}
